package com.mrx.test.junit.extension;

import com.mrx.test.junit.DubboUtils;
import lombok.SneakyThrows;
import org.apache.dubbo.config.annotation.DubboReference;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.TestInstanceFactory;
import org.junit.jupiter.api.extension.TestInstanceFactoryContext;
import org.junit.jupiter.api.extension.TestInstantiationException;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.Arrays;

/**
 * @author Mr.X
 * @since 2023-04-08 09:32
 */
public class XTestExtension implements TestInstanceFactory {

    @Override
    public Object createTestInstance(TestInstanceFactoryContext factoryContext, ExtensionContext extensionContext) throws TestInstantiationException {
        Class<?> testClass = factoryContext.getTestClass();
        try {
            Constructor<?> constructor = testClass.getDeclaredConstructor();
            constructor.setAccessible(true);
            Object instance = constructor.newInstance();
            Arrays.stream(testClass.getDeclaredFields())
                    .filter(it -> it.isAnnotationPresent(DubboReference.class))
                    .forEach(it -> injectReference(instance, it));
            return instance;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @SneakyThrows
    private void injectReference(Object instance, Field field) {
        field.setAccessible(true);
        field.set(instance, DubboUtils.getService(field.getType()));
    }

}
